package com.hxd.qzg;

import java.sql.Connection;

import com.alibaba.druid.filter.logging.Log4j2Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallFilter;
import com.hxd.qzg.common.ScheduledJob;
import com.hxd.qzg.common.model._MappingKit;
import com.hxd.qzg.route.AdminRoute;
import com.hxd.qzg.route.ApiRoute;
import com.hxd.qzg.websocket.WebSocket;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.ext.handler.UrlSkipHandler;
import com.jfinal.json.FastJsonFactory;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.druid.DruidStatViewHandler;
import com.jfinal.server.undertow.UndertowServer;
import com.jfinal.template.Engine;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.log.dialect.log4j2.Log4j2LogFactory;
import cn.hutool.setting.Setting;

public class Config extends JFinalConfig {

	private WallFilter wallFilter;

	private static Prop CONFIG_PROP;
	private static Boolean DEV_MODE;
	private static Setting setting;
	private static String BASE_VIEW_PATH;

	static {
		LogFactory.setCurrentLogFactory(new Log4j2LogFactory());
		CONFIG_PROP = PropKit.use("config.properties");
		setting = new Setting("db.setting", true);
		DEV_MODE = CONFIG_PROP.getBoolean("devMode", false);
		BASE_VIEW_PATH = "templates";
	}

	private static Log logger = LogFactory.get();

	/**
	 * 启动入口，运行此 main 方法可以启动项目，此 main 方法可以放置在任意的 Class 类定义中，不一定要放于此
	 */
	public static void main(String[] args) {
		UndertowServer.create(Config.class).configWeb(builder -> {
			builder.addWebSocketEndpoint(WebSocket.class);
		}).start();
	}

	/**
	 * 配置常量
	 */
	public void configConstant(Constants me) {
		me.setMaxPostSize(Integer.MAX_VALUE);
		// 是否启用调试
		me.setDevMode(DEV_MODE);
		// 设置上传文件大小和路径
		me.setBaseUploadPath(CONFIG_PROP.get("upload.path"));

		me.setMaxPostSize(Integer.MAX_VALUE);
		/**
		 * 支持 Controller、Interceptor、Validator 之中使用 @Inject 注入业务层，并且自动实现 AOP
		 * 注入动作支持任意深度并自动处理循环注入
		 */
		me.setInjectDependency(true);

		// 配置对超类中的属性进行注入
		me.setInjectSuperClass(true);

		me.setJsonFactory(new FastJsonFactory());

		// 自定义异常返回json
		// me.setRenderFactory(new MyErrorFactory());

		me.setJsonDatePattern(DatePattern.NORM_DATETIME_PATTERN);
	}
	/**
	 * 配置路由
	 */
	public void configRoute(Routes me) {
		me.setBaseViewPath(BASE_VIEW_PATH);

		me.add(new ApiRoute());

		me.add(new AdminRoute());

	}

	public void configEngine(Engine me) {

	}

	/**
	 * 配置插件
	 */
	public void configPlugin(Plugins me) {
		// 配置 druid 数据库连接池插件
		DruidPlugin druidPlugin = createDruidPlugin();

		Log4j2Filter log4j2Filter = new Log4j2Filter();
		log4j2Filter.setStatementLogEnabled(true);
		log4j2Filter.setStatementLogErrorEnabled(false);
		log4j2Filter.setStatementExecutableSqlLogEnable(true);
		log4j2Filter.setResultSetLogEnabled(true);
		log4j2Filter.setConnectionConnectAfterLogEnabled(false);
		log4j2Filter.setConnectionConnectBeforeLogEnabled(false);
		log4j2Filter.setConnectionCloseAfterLogEnabled(false);
		log4j2Filter.setConnectionRollbackAfterLogEnabled(false);
		druidPlugin.addFilter(log4j2Filter);

		wallFilter = new WallFilter(); // 加强数据库安全
		wallFilter.setDbType("mysql");
		druidPlugin.addFilter(wallFilter);
		druidPlugin.addFilter(new StatFilter()); // 添加 StatFilter 才会有统计数据
		me.add(druidPlugin);
		// 配置ActiveRecord插件
		ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
		arp.setTransactionLevel(Connection.TRANSACTION_READ_COMMITTED);
		arp.setShowSql(DEV_MODE);
		// 所有映射在 MappingKit 中自动化搞定
		_MappingKit.mapping(arp);
		me.add(arp);
	}

	public static DruidPlugin createDruidPlugin() {
		DruidPlugin druidPlugin = new DruidPlugin(setting.getStr("url"), setting.getStr("username"),
				setting.getStr("password"), setting.getStr("driver"));
		logger.info(DateUtil.date() + "configPlugin 配置Druid数据库连接池过滤器配制");
		return druidPlugin;
	}

	/**
	 * 配置全局拦截器
	 */
	public void configInterceptor(Interceptors me) {
	}

	/**
	 * 配置处理器
	 */
	public void configHandler(Handlers me) {
		DruidStatViewHandler dvh = new DruidStatViewHandler("druid");
		me.add(dvh);
		me.add(new UrlSkipHandler("^/msg.ws", false));
	}

	public void onStart() {
		// 让 druid 允许在 sql 中使用 union
		// https://github.com/alibaba/druid/wiki/%E9%85%8D%E7%BD%AE-wallfilter
		wallFilter.getConfig().setSelectUnionCheck(false);
		logger.info(DateUtil.date() + "start success");
		ScheduledJob.run();
	}

	public void onStop() {
		logger.info(DateUtil.date() + "stop success");
	}
}
